﻿using System;
using System.Collections.Generic;
using System.Web;
using System.IO.Compression;


namespace Tsingda.CacheModule
{
    public class CacheHttpModule : IHttpModule
    {
        public void Dispose()
        {
        }
        private List<string> listNeedCacheExtend;
        public void Init(HttpApplication context)
        {
            context.BeginRequest += new EventHandler(context_BeginRequest);
            context.ReleaseRequestState += new EventHandler(context_ReleaseRequestState);
            listNeedCacheExtend = new List<string>();
            listNeedCacheExtend.Add(".html");
            listNeedCacheExtend.Add(".htm");
            listNeedCacheExtend.Add(".shtml");
            listNeedCacheExtend.Add(".aspx");
        }

        public void context_BeginRequest(object sender, EventArgs e)
        {
            var application = (HttpApplication)sender;
            if (IsNeedCache(application)) //检测当前请求是否需缓存
            {
                #region 使用页面压缩

                ResponseCompressionType compressionType = this.GetCompressionMode(application.Context.Request);
                if (compressionType != ResponseCompressionType.None)
                {
                    application.Context.Response.AppendHeader("Content-Encoding", compressionType.ToString().ToLower());
                    if (compressionType == ResponseCompressionType.GZip)
                    {
                        application.Context.Response.Filter = new GZipStream(application.Context.Response.Filter, CompressionMode.Compress);
                    }
                    else
                    {
                        application.Context.Response.Filter = new DeflateStream(application.Context.Response.Filter, CompressionMode.Compress);
                    }
                }

                #endregion

                string key = application.Context.Request.Url.AbsoluteUri;
                if (application.Context.Request.QueryString["itemid"] != null)
                    CacheManage.cache.StringRootPath = StaticCache.RootPath + "item" + application.Context.Request.QueryString["itemid"] + "\\";
                if (application.Context.Request.QueryString["resourceid"] != null)
                    CacheManage.cache.StringRootPath = StaticCache.RootPath + "resource" + application.Context.Request.QueryString["resourceid"] + "\\";
                if (CacheManage.Container(key))//缓存中存在，则直接返回内容，结束请求
                {
                    CacheManage.Write(application, key);
                    application.CompleteRequest();
                }
            }
        }

        /// <summary>
        /// 检测当前请求是否需缓存,如果是则将此次结果添加至缓存
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        public void context_ReleaseRequestState(object sender, EventArgs e)
        {
            var application = (HttpApplication)sender;
            if (IsNeedCache(application))
            {
                string key = application.Context.Request.Url.AbsoluteUri;
                //是否需要添加缓存，
                if (!CacheManage.Container(key))
                {
                    application.Context.Response.Filter = new ResponseFilter(application.Context.Response.Filter, key);
                }
            }
        }

        public void context_EndRequest(object sender, EventArgs e)
        {
            var application = (HttpApplication)sender;
            string key = application.Context.Request.Url.AbsoluteUri;
            application.Context.Response.Write("<Br>CacheMdule EndRequest");
        }

        /// <summary>
        /// 检测当前请求类型(url扩展名)确定是否需缓存
        /// 如果类型需缓存，但扩展名是html或htm且存在相对应的物理文件的，不执行缓存操作
        /// </summary>
        /// <param name="strFilePath"></param>
        /// <returns></returns>
        private bool IsNeedCache(HttpApplication application)
        {
            bool boolNeedCache = false; //是否需要缓存
            string stringExtend = VirtualPathUtility.GetExtension(application.Context.Request.FilePath).ToLower();
            if (null != listNeedCacheExtend) //url扩展名是否满足条件
            {
                boolNeedCache = listNeedCacheExtend.Contains(stringExtend);
            }

            if (boolNeedCache)
            {

                if (System.IO.File.Exists(application.Context.Request.PhysicalPath)) //存在对应物理文件
                {
                    boolNeedCache = false;
                }

            }

            //特殊业务,对指定ＵＲＬ地址不进行缓存
            //if (application.Context.Request.FilePath.ToLower().Contains("home/index"))
            //    boolNeedCache = false;
            return boolNeedCache;
        }

        /// <summary>
        /// 获取客户端支持的压缩类型
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        private ResponseCompressionType GetCompressionMode(System.Web.HttpRequest request)
        {
            string acceptEncoding = request.Headers["Accept-Encoding"];
            if (string.IsNullOrEmpty(acceptEncoding))
                return ResponseCompressionType.None;

            acceptEncoding = acceptEncoding.ToUpperInvariant();
            if (acceptEncoding.Contains("GZIP"))
                return ResponseCompressionType.GZip;
            else if (acceptEncoding.Contains("DEFLATE"))
                return ResponseCompressionType.Deflate;
            else
                return ResponseCompressionType.None;
        }

        private enum ResponseCompressionType
        {
            None, GZip, Deflate
        }

    }
}
